package com.liuqi.iot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.liuqi.common.base.service.AbstractBaseEntityService;
import com.liuqi.common.base.service.CacheService;
import com.liuqi.common.exception.AppException;
import com.liuqi.iot.bean.dto.DeviceCategoryDTO;
import com.liuqi.iot.bean.dto.DeviceDTO;
import com.liuqi.iot.bean.dto.DeviceModelDTO;
import com.liuqi.iot.bean.dto.GatewayDTO;
import com.liuqi.iot.bean.query.DeviceQuery;
import com.liuqi.iot.domain.entity.DeviceEntity;
import com.liuqi.iot.domain.mapper.DeviceMapper;
import com.liuqi.iot.service.*;
import com.liuqi.sys.common.ErrorCodes;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 设备服务实现 
 * @author Coder Generator 2025-03-22 15:29:30 
 **/
@Service
public class DeviceEntityServiceImpl extends AbstractBaseEntityService<DeviceEntity, DeviceDTO, DeviceMapper, DeviceQuery> implements DeviceEntityService {
    @Autowired
    private CacheService cacheService;

    @Autowired
    private DeviceHistoryDataService historyDataService;

    @Autowired
    private GatewayEntityService gatewayEntityService;

    @Autowired
    private DeviceModelEntityService modelEntityService;

    @Autowired
    private DeviceCategoryEntityService categoryEntityService;

    @Override
    protected QueryWrapper<DeviceEntity> queryToWrapper(DeviceQuery query) {
        return this.createQueryWrapper()
                .eq(StringUtils.isNotBlank(query.getId()), "id", query.getId())
                .in(null != query.getIds(), "id", query.getIds())
                .eq(StringUtils.isNotBlank(query.getGatewayId()), "gateway_id", query.getGatewayId())
                .eq(StringUtils.isNotBlank(query.getModelId()), "model_id", query.getModelId())
                .eq(StringUtils.isNotBlank(query.getCategoryId()), "category_id", query.getCategoryId())
                .eq(StringUtils.isNotBlank(query.getCode()), "code", query.getCode())
                .eq(StringUtils.isNotBlank(query.getName()), "name", query.getName())
                .eq(null != query.getStatus(), "status", query.getStatus())
                .and(StringUtils.isNotBlank(query.getKey()), q -> {
                    q.like("code", query.getKey())
                            .or(q1 -> q1.like("name", query.getKey()));
                })
                .orderByDesc("create_time");
    }

    /**
     * 补充模型、网关及分类相关名称等信息
     */
    @Override
    public void appendOtherInfo(List<DeviceDTO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        // 补充网关、分类及模型名称
        List<String> gatewayIds = new ArrayList<>(16);
        List<String> modelIds = new ArrayList<>(16);
        List<String> categoryIds = new ArrayList<>(16);
        list.forEach(device -> {
            gatewayIds.add(device.getGatewayId());
            modelIds.add(device.getModelId());
            categoryIds.add(device.getCategoryId());
        });

        Map<String, GatewayDTO> gatewayMap = gatewayEntityService.findByIds(gatewayIds)
                .stream()
                .collect(Collectors.toMap(GatewayDTO::getId, i -> i));

        Map<String, String> modelMap = modelEntityService.findByIds(modelIds)
                .stream()
                .collect(Collectors.toMap(DeviceModelDTO::getId, DeviceModelDTO::getName));
        Map<String, String> categoryMap = categoryEntityService.findByIds(categoryIds)
                .stream()
                .collect(Collectors.toMap(DeviceCategoryDTO::getId, DeviceCategoryDTO::getName));
        list.forEach(device -> {
            Optional.ofNullable(gatewayMap.get(device.getGatewayId())).ifPresent(gateway -> {
                device.setGatewayName(gateway.getName());
                device.setGatewayCode(gateway.getCode());
            });
            device.setModelName(modelMap.get(device.getModelId()));
            device.setCategoryName(categoryMap.get(device.getCategoryId()));
        });
    }

    /**
     * 更新记录
     *
     * @param dto 待更新记录内容，id不能为空
     */
    @Override
    public void update(DeviceDTO dto) {
        super.update(dto);
        cacheService.remove("iot.device." + dto.getCode());
    }

    /**
     * 通过设备编号查询设备
     *
     * @param code 设备编号
     * @return 设备信息
     */
    @Override
    public Optional<DeviceDTO> findByCode(String code) {
        return Optional.ofNullable(cacheService.getOrCache("iot.device." + code, DeviceDTO.class, () -> {
            DeviceQuery q = new DeviceQuery();
            q.setCode(code);
            return this.findOne(q).orElse(null);
        }));
    }

    /**
     * 自动更新设备离线状态
     */
    @Override
    public void updateStatusAuto() {
        baseMapper.updateStatusAuto();
    }

    /**
     * 设备下线
     */
    @Override
    public void offline(String id) {
        DeviceDTO exp = new DeviceDTO();
        exp.setStatus(3);
        exp.setId(id);
        this.update(exp);
    }

    /**
     * 设备发布
     */
    @Override
    public void publish(String id) {
        DeviceDTO device = this.findById(id).orElseThrow(AppException.supplier(ErrorCodes.IOT_DEVICE_NOT_EXISTS));

        // 更新设备状态
        device.setStatus(1);
        this.update(device);

        // 创建表
        historyDataService.createTable(device.getCode());
    }
}